#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include "Socket.hpp"
#include "Epoller.hpp"
#include "Connection.hpp"
#include "logmsg.pb.h"
#include "../../logs/log.h"
#define EPOLL_BLOCK -1
using namespace Net_Work;
using namespace EpollerModule;
// 采用Epoll来实现多个连接的监听
class TcpServer
{
    static const int gmaxevents = 64;

public:
    using ptr = std::shared_ptr<TcpServer>;
    TcpServer() : _running(false),
                  _epoller(new Epoller()),
                  _timeout(EPOLL_BLOCK)
    {
        _epoller->InitEpoller();
    }
    void AddConnection(Connection *conn)
    {
        if (!conn)
            return;
        if (IsConnectionExists(conn->SockFd()))
            return;

        // 1.添加TcpServer unordered_map
        _connections[conn->SockFd()] = conn;

        // 2. 让epoller管理起来(读写)
        _epoller->AddEvent(conn->SockFd(), conn->Events());
    }

    void RemoveConnection(int sockfd)
    {
        // 这里
        if (!IsConnectionExists(sockfd))
            return;
        // 1.清理connection关心的事件
        _connections[sockfd]->SetEvents(0);
        // 2.清理epoller中对sockfd的关心
        _epoller->DelEvent(sockfd);
        // 3.移除在_connection中的key和value
        _connections.erase(sockfd);
    }
    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (!IsConnectionExists(sockfd))
            return;
        uint32_t events = (readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET;

        // 1.修改connection自己关心的事件
        _connections[sockfd]->SetEvents(events);
        // 2.把关心的事件, 传入到内核中
        _epoller->ModEvent(sockfd, _connections[sockfd]->Events());
    }
    // 事件派发
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, gmaxevents, timeout);

        // 处理事件
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;
            // 将所有的epoll检测到的fd的问题，最后统一转换成为读写错误
            if (events & EPOLLERR)
                events |= (EPOLLIN | EPOLLOUT);
            if (events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);
            // 所有的IO操作,都会转化为下面的部分
            // 这都是在进行事件的派发, 事件就绪就把任务派发给对应的IO操作函数
            if ((events & EPOLLIN) && IsConnectionExists(sockfd))
            {
                // 保证读写方法存在且合法
                if (_connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }
            if ((events & EPOLLOUT) && IsConnectionExists(sockfd))
            {
                // std::cout << "对写事件进行处理" << std::endl;
                if (_connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
                std::cout << "对写事件处理完毕" << std::endl;
            }
        }
    }
    // 入口
    void Dispatcher()
    {
        _running = true;
        while (_running)
        {
            // _epoller->DebugFdList();
            LoopOnce(_timeout); // 事件派发
        }
        _running = false;
    }

private:
    bool IsConnectionExists(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        else
            return true;
    }

private:
    std::unordered_map<int, Connection *> _connections;
    std::unique_ptr<Epoller> _epoller;
    // Epoller _epoller;
    struct epoll_event _revs[gmaxevents];
    bool _running;
    int _timeout;
};
